/*
 ********************************************************************************
 * Copyright (c) 2012 Samsung Electronics, Inc.
 * All rights reserved.
 *
 * This software is a confidential and proprietary information of Samsung
 * Electronics, Inc. ("Confidential Information"). You shall not disclose such
 * Confidential Information and shall use it only in accordance with the terms
 * of the license agreement you entered into with Samsung Electronics.
 ********************************************************************************
 */

package com.manojbhadane.view;

import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;

import com.manojbhadane.semicircle.BuildConfig;

public class CircleListView extends ListView implements OnScrollListener
{

	private static final int DEFAULT_SCROLL_DURATION = 200;
	private static final boolean DEBUG = BuildConfig.DEBUG && false;
	public static final int DEFAULT_SELECTION = Integer.MAX_VALUE / 2;
	private static final String TAG = CircleListView.class.getSimpleName();

	private boolean mIsForceCentering;
	private ViewModifier mViewModifier;
	private int mScrollDuration = DEFAULT_SCROLL_DURATION;
	private OnItemCenteredListener mOnItemCenteredListener;
	private final CenterRunnable mCenterRunnable = new CenterRunnable();

	public CircleListView(Context context, AttributeSet attrs)
	{
		super(context, attrs);

		super.setOnScrollListener(this);

		setOverscrollFooter(null);
		setOverscrollHeader(null);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b)
	{
		super.onLayout(changed, l, t, r, b);

		setSelection(DEFAULT_SELECTION);
	}

	@Override
	protected void onScrollChanged(int l, int t, int oldl, int oldt)
	{
		super.onScrollChanged(l, t, oldl, oldt);

		if (mViewModifier != null)
		{

			final int count = getChildCount();
			for (int i = 0; i < count; ++i)
			{
				View v = getChildAt(i);

				mViewModifier.applyToView(v, this);
			}
		}
	}

	/**
	 * Sets the current {@link ViewModifier} for this list.
	 * 
	 * @param modifier
	 *            implementation of the {@link ViewModifier} class
	 * 
	 * @see ViewModifier
	 */
	public void setViewModifier(ViewModifier modifier)
	{
		mViewModifier = modifier;
	}

	/**
	 * Sets the smooth scroll duration.
	 * 
	 * @param duration
	 *            the number of milliseconds the scrolling animation will take
	 */
	public void setScrollDuration(int duration)
	{
		mScrollDuration = duration;
	}

	/**
	 * Sets the listener object that will be notified when the list centers on
	 * an item.
	 * 
	 * @param listener
	 *            the {@link OnItemCenteredListener} implementation
	 */
	public void setOnItemCenteredListener(OnItemCenteredListener listener)
	{
		mOnItemCenteredListener = listener;
	}

	/**
	 * Smoothly scrolls the {@link CircleListView} so the {@link View} v is in
	 * the middle.
	 * 
	 * @param v
	 *            the {@link View} that should be in the center after the scroll
	 * @param scrollDuration
	 *            how long will the scroll take
	 */
	public void smoothScrollToView(View v)
	{
		final float y = v.getY() + v.getHeight() * 0.5f;
		final float halfHeight = getHeight() * 0.5f;
		final int distance = (int) (y - halfHeight);

		smoothScrollBy(distance, mScrollDuration);
	}

	@Override
	public void setOnScrollListener(OnScrollListener l)
	{
		throw new UnsupportedOperationException();
	}

	public void onScrollStateChanged(AbsListView view, int scrollState)
	{
		if (scrollState == SCROLL_STATE_IDLE)
		{

			if (!mIsForceCentering)
			{
				// Start centering the view

				mIsForceCentering = true;

				final View childView = findViewAtCenter();

				if (childView != null)
				{
					if (DEBUG)
					{
//						TextView tv = (TextView) childView.findViewById(R.id.label_app_name);
//						Log.d(TAG, "Application in center: " + tv.getText().toString());
					}

					if (mOnItemCenteredListener != null)
					{
						mOnItemCenteredListener.onItemCentered(childView);
					}

					mCenterRunnable.setView(childView);
					ViewCompat.postOnAnimation(this, mCenterRunnable);
				}
			}
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev)
	{

		removeCallbacks(mCenterRunnable);

		mIsForceCentering = false;

		return super.onTouchEvent(ev);
	}

	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
	{

	}

	/**
	 * Finds a View located at the specified point.
	 * 
	 * @param x
	 *            x-coordinate of the point
	 * @param y
	 *            y-coordinate of the point
	 * @return {@link View} located at (x, y) or <code>null</code> if not found
	 */
	public View findViewAt(int x, int y)
	{
		final int count = getChildCount();
		for (int i = 0; i < count; ++i)
		{
			final View v = getChildAt(i);
			final int x0 = v.getLeft();
			final int y0 = v.getTop();
			final int x1 = v.getWidth() - x0;
			final int y1 = v.getHeight() + y0;

			if (x >= x0 && x <= x1 && y >= y0 && y <= y1)
			{
				return v;
			}
		}

		return null;
	}

	/**
	 * Finds a {@link View} located in the center of the {@link CircleListView}.
	 * 
	 * @return the {@link View} at the center of the {@link CircleListView}
	 */
	public View findViewAtCenter()
	{
		return findViewAt(0, getHeight() / 2);
	}

	public class CenterRunnable implements Runnable
	{

		private View mView;

		public void setView(View v)
		{
			mView = v;
		}

		public void run()
		{
			smoothScrollToView(mView);

			mIsForceCentering = true;
		}
	}

	/**
	 * Handles the event occurring when the list centers on an item.
	 * 
	 * @see CircleListView#setOnItemCenteredListener(OnItemCenteredListener)
	 */
	public interface OnItemCenteredListener
	{
		public void onItemCentered(View v);
	}
}
